#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>

#include "1.h"

#define GRIDSIZE 15
#define judge_black 0
#define judge_white 1
#define grid_blank 0
#define grid_black 1
#define grid_white -1

using namespace std;

int currBotColor;                        // 本方所执子颜色（1为黑，-1为白，棋盘状态亦同）
int gridInfo[GRIDSIZE][GRIDSIZE] = {0};  // 先x后y，记录棋盘状态
int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};

// 定义各种棋型的数组
// 黑棋是1 白棋是-1 空是0 2是障碍 实际处理时候 对方的棋子和出界都看作障碍
// 只找: 活五  眠五  活四  眠四  活三 朦胧三  眠三  活二 眠二
// 下标: A5   B5   A4   B4   A3   B3     C3   A2   B2
// 后面是有对称的 后来还是发现不考虑对称太麻烦了
string BlackShapeA6[] = {"111111"};  // 114514
string BlackShapeA5[] = {"0111110", "00111101", "100111001", "10111100"};
string BlackShapeB5[] = {"20111101", "2111101", "2111110", "1101101" /*对称*/, "10111102", "1011112", "0111112", "1011011"};
string BlackShapeA4[] = {"00111100"};
string BlackShapeB4[] = {"20111100",          "2111100", "011011", "110011", "110101",
                         /*对称*/ "00111102", "0011112", "110110", "101011"};
string BlackShapeA3[] = {"00111000", "00110100", /*对称*/ "00011100", "00101100"};
string BlackShapeB3[] = {"20111000", "20011100", "00101010", /*对称*/ "00011102", "00111002", "01010100"};
string BlackShapeC3[] = {"20011102",          "200101012", "20101012", "20001112",
                         /*对称*/ "20111002", "210101002", "21010102", "21110002"};
string BlackShapeA2[] = {"00110000", "00011000", "00101000", "00100100", /*对称*/ "00001100", "00010100"};
string BlackShapeB2[] = {"010001", "2100100", "20100100", "2110000", /*对称*/ "100010", "0010012", "00100102", "0000112"};

// 白棋本来是-1但是字符串匹配不太方便, 这里用3代替, 生成每行字符串的时候要注意
string WhiteShapeA6[] = {"111111"};
string WhiteShapeA5[] = {"0333330", "00333303", "300333003", "30333300"};
string WhiteShapeB5[] = {"20333303", "2333303", "2333330", "3303303" /*对称*/, "30333302", "3033332", "0333332", "3033033"};
string WhiteShapeA4[] = {"00333300"};
string WhiteShapeB4[] = {"20333300",          "2333300", "033033", "330033", "330303",
                         /*对称*/ "00333302", "0033332", "330330", "303033"};
string WhiteShapeA3[] = {"00333000", "00330300", /*对称*/ "00033300", "00303300"};
string WhiteShapeB3[] = {"20333000", "20033300", "00303030", /*对称*/ "00033302", "00333002", "03030300"};
string WhiteShapeC3[] = {"20033302",          "200303032", "20303032", "20003332",
                         /*对称*/ "20333002", "230303002", "23030302", "23330002"};
string WhiteShapeA2[] = {"00330000", "00033000", "00303000", "00300300", /*对称*/ "00003300", "00030300"};
string WhiteShapeB2[] = {"030003", "2300300", "20300300", "2330000", /*对称*/ "300030", "0030032", "00300302", "0000332"};

// 判断是否在棋盘内
inline bool inMap(int x, int y) {
    if (x < 0 || x >= GRIDSIZE || y < 0 || y >= GRIDSIZE) return false;
    return true;
}

// 在坐标处落子，检查是否合法或模拟落子
bool ProcStep(int x0, int y0, int x1, int y1, int grid_color, bool check_only) {
    if (x1 == -1 || y1 == -1) {
        if (!inMap(x0, y0) || gridInfo[x0][y0] != grid_blank) return false;
        if (!check_only) {
            gridInfo[x0][y0] = grid_color;
        }
        return true;
    } else {
        if ((!inMap(x0, y0)) || (!inMap(x1, y1))) return false;
        if (gridInfo[x0][y0] != grid_blank || gridInfo[x1][y1] != grid_blank) return false;
        if (!check_only) {
            gridInfo[x0][y0] = grid_color;
            gridInfo[x1][y1] = grid_color;
        }
        return true;
    }
}

string from_arrayline_to_string(int gridArray[15][15], int typeint, int color) {
    // 把数组的某一部分抽象成string
    // 坐标按照老师pdf的坐标建系!!!!!!!!!!!!!
    // 根据传入的颜色不同 返回字符串不尽相同 如果传入-1(白棋) 则黑棋和边界都会是2 反之亦然 两侧边界会有额外的2
    // typeint是一个返回哪一行/列/对角线位置的标识变量
    // 00~14 x=0到x=14
    // 100~114 y=0到y=14
    // 191~209 返回y=x-9到y=x+9这两条对角线上的字符串
    // 305~323 返回x+y=5到x+y=23这两条对角线上的字符串
    string returnresult;
    returnresult.reserve(17);
    // 把color从表示颜色的int转换为表示颜色的字符'1'和'3'
    if (color == grid_white) color = '3';
    if (color == grid_black) color = '1';
    if (typeint >= 0 && typeint <= 14) {
        // 这是返回x=typeint的字符串
        int realnumber = typeint;
        // 0和第16位是2 边缘看作障碍 1到15位存取棋盘对应行的0~14
        returnresult.push_back('2');
        for (int i = 0; i <= 14; i++) {
            if (gridArray[i][realnumber] == 0)
                returnresult.push_back('0');
            else if (gridArray[i][realnumber] == color)
                returnresult.push_back(color);
            else
                returnresult.push_back('2');
        }
        returnresult.push_back('2');
        return std::move(returnresult);
    } else if (typeint >= 100 && typeint <= 114) {
        int realnumber = typeint - 100;
        // 0和第16位是2 边缘看作障碍 1到15位存取棋盘对应行的0~14
        returnresult.push_back('2');
        for (int i = 0; i <= 14; i++) {
            if (gridArray[realnumber][i] == 0)
                returnresult.push_back('0');
            else if (gridArray[realnumber][i] == color)
                returnresult.push_back(color);
            else
                returnresult.push_back('2');
        }
        returnresult.push_back('2');
        return std::move(returnresult);
    } else if (typeint >= 191 && typeint <= 209) {
        // y=x-9到y=x+9
        int realnumber = typeint - 200;
        returnresult.push_back('2');
        if (realnumber <= 0 && realnumber >= -9) {
            // 这个时候以和x轴的交点作为起始点延伸
            int xbegin = -realnumber;
            int ybegin = 0;
            while (inMap(xbegin, ybegin)) {
                if (gridArray[xbegin][ybegin] == 0)
                    returnresult.push_back('0');
                else if (gridArray[xbegin][ybegin] == color)
                    returnresult.push_back(color);
                else
                    returnresult.push_back('2');

                xbegin++;
                ybegin++;
            }
            returnresult.push_back('2');
        } else {
            // 以y轴的点作为起点延伸
            int xbegin = 0;
            int ybegin = realnumber;
            while (inMap(xbegin, ybegin)) {
                if (gridArray[xbegin][ybegin] == 0)
                    returnresult.push_back('0');
                else if (gridArray[xbegin][ybegin] == color)
                    returnresult.push_back(color);
                else
                    returnresult.push_back('2');

                xbegin++;
                ybegin++;
            }
            returnresult.push_back('2');
        }
        return std::move(returnresult);
    } else if (typeint <= 323 && typeint >= 305) {
        // 返回x+y=5到x+y=23上面的字符串
        int realnumber = typeint - 300;
        if (realnumber >= 5 && realnumber <= 14) {
            int xbegin = realnumber;
            int ybegin = 0;
            while (inMap(xbegin, ybegin)) {
                if (gridArray[xbegin][ybegin] == 0)
                    returnresult.push_back('0');
                else if (gridArray[xbegin][ybegin] == color)
                    returnresult.push_back(color);
                else
                    returnresult.push_back('2');
                ybegin--;
                xbegin++;
                returnresult.push_back('2');
            }
        } else {
            // 此时是x+y=15到x+y=23
            int xbegin = realnumber - 14;
            int ybegin = 14;
            while (inMap(xbegin, ybegin)) {
                if (gridArray[xbegin][ybegin] == 0)
                    returnresult.push_back('0');
                else if (gridArray[xbegin][ybegin] == color)
                    returnresult.push_back(color);
                else
                    returnresult.push_back('2');
                ybegin--;
                xbegin++;
            }
            returnresult.push_back('2');
        }
        return std::move(returnresult);
    } else {
        printf("ERROR in function from_arrayline_to_string!\n");
        exit(1);
    }
}

Situation get_situation(int gridArray[15][15], int color) {
    // 返回color的一个Situation实例
    for (int i = 0; i <= 14; i++) {
    }
}

int main() {
    int x0, y0, x1, y1;
    // 用来存储最终搜索的范围: 周围都有棋子
    // -1:这个地方已经有棋子了 0:这个地方没有棋子但是周围也没有棋子 1:这个地方没有棋子且周围有棋子
    int ToSearchSet[15][15]{0};

    // 分析自己收到的输入和自己过往的输出，并恢复棋盘状态
    int turnID;  // 即将进行的棋局数
    cin >> turnID;
    currBotColor = grid_white;  // 先假设自己是白方
    for (int i = 0; i < turnID; i++) {
        // 根据这些输入输出逐渐恢复状态到当前回合
        // 首先是对手行动
        cin >> x0 >> y0 >> x1 >> y1;
        if (x0 == -1 && y0 == -1)
            currBotColor = grid_black;  // 第一回合收到坐标是-1, -1，说明我是黑方
        else {
            ProcStep(x0, y0, x1, y1, -currBotColor, false);  // 模拟对方落子
            ToSearchSet[x0][y0] = -1;
            for (int i = 0; i <= 7; i++) {
                int curx = x0 + dx[i];
                int cury = y0 + dy[i];
                if (inMap(curx, cury) && ToSearchSet[curx][cury] == 0) ToSearchSet[curx][cury] = 1;
            }
            ToSearchSet[x1][y1] = -1;
            for (int i = 0; i <= 7; i++) {
                int curx = x1 + dx[i];
                int cury = y1 + dy[i];
                if (inMap(curx, cury) && ToSearchSet[curx][cury] == 0) ToSearchSet[curx][cury] = 1;
            }
        }

        // 然后是本方当时的行动
        // 对手行动总比自己行动多一个
        if (i == turnID - 1) break;  // 该你下了，不用读取了

        cin >> x0 >> y0 >> x1 >> y1;
        ProcStep(x0, y0, x1, y1, currBotColor, false);  // 模拟己方落子
        ToSearchSet[x0][y0] = -1;
        for (int i = 0; i <= 7; i++) {
            int curx = x0 + dx[i];
            int cury = y0 + dy[i];
            if (inMap(curx, cury) && ToSearchSet[curx][cury] == 0) ToSearchSet[curx][cury] = 1;
        }
        ToSearchSet[x1][y1] = -1;
        for (int i = 0; i <= 7; i++) {
            int curx = x1 + dx[i];
            int cury = y1 + dy[i];
            if (inMap(curx, cury) && ToSearchSet[curx][cury] == 0) ToSearchSet[curx][cury] = 1;
        }
    }

    // 现在确定搜索的范围
    vector<Point> SearchSet;
    SearchSet.reserve(50);
    for (int i = 0; i < GRIDSIZE; i++) {
        for (int j = 0; j < GRIDSIZE; j++) {
            if (ToSearchSet[i][j] == 1) SearchSet.push_back({i, j});
        }
    }

    // 至此 有用的变量: SearchSet(里面都是Point类 包含可能的考虑节点) gridInfo(黑子1 白子-1 包含棋盘的情况)
    //  cout << startX << ' ' << startY << ' ' << resultX << ' ' << resultY << endl;
    return 0;
}
